package com.beiding.jsonanalyzer.analyze;

import com.beiding.jsonanalyzer.Key;
import com.beiding.jsonanalyzer.analyze.func.FuncBase;
import com.beiding.jsonanalyzer.flow.ValueNode;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

/**
 * 排序器
 */
public class Orderer {

    private KeyMode keyMode = KeyMode.NORMAL;

    private List<SortParam> sortParams = new ArrayList<>();

    /**
     * 定义一个排序的引用
     *
     * @param refer
     * @param sortFunc
     * @return
     */
    public Orderer by(Object refer, Comparator<Object> sortFunc) {
        /*
        可以使用任意对象进行排序
         */
        refer = KeyUtils.handleKey(refer, keyMode);
        //如果不是refer不是key类型,就是常量,常量永远相等不需要比较,直接跳过
        if (!(refer instanceof Key) && !(refer instanceof FuncBase)) {
            return this;
        }
        SortParam sortParam = new SortParam(refer, sortFunc);
        sortParams.add(sortParam);
        return this;
    }

    public Orderer by(Object refer, OrderEnum innerSort) {
        return by(refer, innerSort.sortFunc);
    }

    /**
     * 默认升序排序
     *
     * @param refer
     * @return
     */
    public Orderer by(Object refer) {
        return by(refer, OrderEnum.ASC);
    }


    public <W extends ValueNode> List<W> orderFor(List<W> valueNodes) {

        //取出来所有的
        List<W> r = new ArrayList<>(valueNodes);

        r.sort((a, b) -> {

            Object left = a.get();
            Object right = b.get();

            //逐个过排序器,如果为0就一直比较向后比较,如果能定下来顺序就直接返回定序结果
            for (SortParam sortParam : sortParams) {
                Object refer = sortParam.refer;

                Object lv = ValueUtils.execExpression(left, refer, Object.class);
                Object rv = ValueUtils.execExpression(right, refer, Object.class);
                Comparator<Object> sortFunc = sortParam.sortFunc;
                int sort = sortFunc.compare(lv, rv);

                //只要两个值比较出来的结果不等于0 就一定能排出先后 返回比较结果并结束
                if (sort != 0) {
                    return sort;
                }

            }

            return 0;

        });
        return r;
    }




    private static Comparator<Object> ascFunc = (left, right) -> {
            /*

                默认排序器支持排序的类型有
                1. 数字
                2. 字符串
                3. 布尔型

                被比较的两个类型必须是相同类型
                如果不是相同类型的则报错,提示不可比较

             */

        if (left == null) {
            if (right == null) {
                return 0;
            } else {
                return 1;
            }
        }

        //空值判断
        if (right == null) {
            return -1;
        }

        if (left instanceof Number) {
            if (right instanceof Number) {
                return Double.compare(((Number) left).doubleValue(), ((Number) right).doubleValue());
            }
        }

        if (left instanceof String) {
            if (right instanceof String) {
                return ((String) left).compareTo((String) right);
            }
        }

        if (left instanceof Boolean) {

            if (right instanceof Boolean) {
                return ((Boolean) left).compareTo((Boolean) right);
            }

        }

        //如果类型不一致,或类型不支持,直接比较hash
        return Integer.compare(left.hashCode(), right.hashCode());

    };

    private static Comparator<Object> descFunc = (left, right) -> ascFunc.compare(right, left);

    public enum OrderEnum {
        ASC(ascFunc),
        DESC(descFunc);
        private Comparator<Object> sortFunc;

        OrderEnum(Comparator<Object> sortFunc) {
            this.sortFunc = sortFunc;
        }
    }

    private static class SortParam {
        private Object refer;
        private Comparator<Object> sortFunc;

        public SortParam(Object refer, Comparator<Object> sortFunc) {
            this.refer = refer;
            this.sortFunc = sortFunc;
        }
    }

    public Orderer keyMode(KeyMode keyMode) {
        this.keyMode = keyMode;
        return this;
    }

}
